#ifndef PRUEBACOMPRESORARIMETICO_H_
#define PRUEBACOMPRESORARIMETICO_H_

#define private public

#include "../CompresorAritmetico.h"
#include "../TablaDeFrecuencias.h"
#include "../BloqueBSharp.h"
#include "pruebaBloqueBSharp.h"
#include <iostream>

#include <string>
#include <stdlib.h>
#include <time.h>

using namespace Toolkit;
using namespace std;

bool pruebaCalcularRango()
{
	bool resultadoPrueba = true;

	char caracter = 'a';
	TablaDeFrecuencias tabla;

	CompresorAritmetico::instancia().calcularRango(caracter, tabla,
												   CompresorAritmetico::instancia().piso,
												   CompresorAritmetico::instancia().techo);

	//valores calculados con HP49
	resultadoPrueba = resultadoPrueba && (1627389952 == CompresorAritmetico::instancia().piso);
	resultadoPrueba = resultadoPrueba && (1644167167 == CompresorAritmetico::instancia().techo);

	if (!resultadoPrueba)
	{
		cout << "funciona mal calcular rango";
	}

	return resultadoPrueba;
}

bool pruebaDescomprimirTextoRandom()
{
	bool resultadoPrueba = true;

	string textoAcomprimir;
	srand(time(NULL));

	int cantidad = 30000;

	for(int i = 0; i < cantidad; i++)
	{
		textoAcomprimir += "ab";
	}


	string textoComprimido = CompresorAritmetico::instancia().comprimir(textoAcomprimir);
	string resultadoDescomprimido = CompresorAritmetico::instancia().descomprimir(textoComprimido);

	for (unsigned int i = 0; i < textoAcomprimir.size(); i++)
	{
		if (textoAcomprimir[i] != resultadoDescomprimido[i])
		{
			resultadoPrueba = false;
			break;
		}
	}

	if ( textoAcomprimir.size() !=  resultadoDescomprimido.size() )
		resultadoPrueba = false;

	if (!resultadoPrueba)
	{
		cout << "funciona mal pruebaDescomprimirTextoRandom" << endl;
	}

	return resultadoPrueba;
}

bool pruebaDescomprimirBasica()
{
	bool resultadoPrueba = true;

	string textoNormal = "Welcome to the home page for the 97 Things Every Programmer"
			" Should Know project, pearls of wisdom for programmers collected from leading"
			" practitioners. You can read through the Edited Contributions, browse "
			"Contributions in Progress, view the list of current Contributors, and also "
			"learn How to Become a Contributor. If you would simply like to comment on a "
			"contribution, please also read How to Become a Contributor as some of it "
			"applies to you. There is no overarching narrative: The collection is intended"
			" simply to contain multiple and varied perspectives on what it is that "
			"contributors to the project feel programmers should know. This can be anything "
			"from code-focused advice to culture, from algorithm usage to agile thinking, "
			"from implementation know-how to professionalism, from style to substance, etc."
			"The deadline for having something considered for inclusion in the the book "
			"form of the project has passed. Following some further editing over the next"
			" few weeks, 97 contributions will be picked from the Edited Contributions and"
			" published in O'Reilly's 97 Things series, which already includes 97 Things "
			"Every Software Architect Should Know (also see the 97 Things Every Software"
			" Architect Should Know homepage) and 97 Things Every Project Manager Should"
			" Know. You can find out more about the series and the 97 Things Every"
			" Programmer Should Know project in this InfoQ article.The 97 chosen for the"
			" book will be the ones considered to fit best together, and not simply "
			"the ones that are individually the best. Each contributor whose contribution"
			" goes into the book will be fully acknowledged in the book and will get a"
			" complementary copy of the book when it is published. The contributions for "
			"the site are being edited by Kevlin Henney, who will also be listed as the "
			"editor of the published book. ";

	string stringAComprimir =
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

	string resultadoComprimido = CompresorAritmetico::instancia().comprimir(textoNormal);
	string resultadoDescomprimido = CompresorAritmetico::instancia().descomprimir(resultadoComprimido);

	for (unsigned int i = 0; i < textoNormal.size(); i++)
	{
		if (textoNormal[i] != resultadoDescomprimido[i])
		{
			resultadoPrueba = false;
			break;
		}
	}

	if (!resultadoPrueba)
	{
		cout << "funciona mal pruebaDescomprimirBasica";
	}

	return resultadoPrueba;
}

void pruebaGeneralArimetico()
{
	bool resultadoPrueba = true;

//	resultadoPrueba = resultadoPrueba && pruebaCalcularRango();
	//resultadoPrueba = resultadoPrueba && pruebaDescomprimirBasica();
	resultadoPrueba = resultadoPrueba && pruebaDescomprimirTextoRandom();

	if (resultadoPrueba)
	{
		cout << "OK";
	}
}

#endif /* PRUEBACOMPRESORARIMETICO_H_ */
